/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.apisupport; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.jar.*; import javax.swing.event.*; import org.openide.*; import org.openide.filesystems.FileObject; import org.openide.modules.ModuleDescription; import org.openide.nodes.*; import org.openide.util.HelpCtx; import org.openide.util.WeakListener; public class InstanceNode extends FilterNode { private ManifestProvider provider; private Object type; private int style; private String val; private ChangeListener list; public InstanceNode (ManifestProvider provider, Object type, int style, String val, Node baseNode) { super (baseNode); this.provider = provider; this.type = type; this.style = style; this.val = val; provider.addChangeListener (WeakListener.change (list = new ChangeListener () { public void stateChanged (ChangeEvent ev) { fPC (); } }, provider)); } private void fPC () { firePropertyChange (null, null, null); } public HelpCtx getHelpCtx () { return new HelpCtx ("org.netbeans.modules.apisupport.modules"); } public boolean canCopy () { return false; // maybe later } public boolean canCut () { return false; // maybe later } public boolean canRename () { return false; } public boolean canDestroy () { return true; } private static class HexBufferInputStream extends InputStream { private String buf; private int len; private int pos; private static final String digits = "0123456789ABCDEF"; public HexBufferInputStream (String contents) { buf = contents; len = buf.length (); pos = 0; } public void close () throws IOException { buf = null; } public int read () throws IOException { if (pos == len) return -1; if (pos == len - 1) throw new IOException ("odd # of chars in hex string!"); char hi = buf.charAt (pos++); int numHi = digits.indexOf (hi); if (numHi == -1) throw new IOException ("bad hex digit: " + hi); char lo = buf.charAt (pos++); int numLo = digits.indexOf (lo); if (numLo == -1) throw new IOException ("bad hex digit: " + lo); return numHi * 16 + numLo; } } public void destroy () throws IOException { Manifest mani = provider.getManifest (); String associatedFiles = null; // Remove manifest attributes. if (style == CategoryNode.STYLE_MAIN) { Attributes attr = mani.getMainAttributes (); attr.remove (type); if (type.equals (ModuleDescription.TAG_MAIN) && attr.containsKey (CategoryNode.ATTR_FILEOBJS_INSTALL)) { associatedFiles = attr.getValue (CategoryNode.ATTR_FILEOBJS_INSTALL); attr.remove (CategoryNode.ATTR_FILEOBJS_INSTALL); } else if (type.equals (ModuleDescription.TAG_DESCRIPTION) && attr.containsKey (CategoryNode.ATTR_FILEOBJS_HELPSET)) { associatedFiles = attr.getValue (CategoryNode.ATTR_FILEOBJS_HELPSET); attr.remove (CategoryNode.ATTR_FILEOBJS_HELPSET); } } else if (style == CategoryNode.STYLE_SECTION) { // May still be null after this, OK: associatedFiles = mani.getAttributes (val).getValue (CategoryNode.ATTR_FILEOBJS_SECTION); mani.getEntries ().remove (val); } else { // XXX STYLE_DEP implement return; } provider.setManifest (mani); // Possibly remove any associated files with this instance, if such were included // at the time the instance was added via a paste. if (associatedFiles != null) { // hello, imports?! java.io.InputStream is = new HexBufferInputStream (associatedFiles.trim ()); java.io.ObjectInputStream ois = new java.io.ObjectInputStream (is); FileObject[] files; try { files = (FileObject[]) ois.readObject (); } catch (ClassNotFoundException cnfe) { throw new IOException (cnfe.getMessage ()); } ois.close (); is.close (); provider.removeFiles (new HashSet (Arrays.asList (files))); } } public Node.PropertySet[] getPropertySets () { Node.PropertySet[] orig = super.getPropertySets (); Node.PropertySet[] nue = new Node.PropertySet[orig.length + 1]; nue[0] = getExtraSet (); for (int i = 0; i < orig.length; i++) nue[i + 1] = orig[i]; return nue; } private Sheet.Set xtra = null; private Sheet.Set getExtraSet () { if (xtra == null) { xtra = new Sheet.Set (); xtra.setName ("manifestprops"); xtra.setDisplayName ("OpenIDE Manifest"); xtra.setShortDescription ("Configure how this object will appear in a module manifest."); class NameProp extends PropertySupport.ReadOnly { public NameProp () { super ("name", String.class, "Resource Path", "Path to the object within the module."); } public Object getValue () { return val; } } xtra.put (new NameProp ()); class ExistsProp extends PropertySupport.ReadOnly { public ExistsProp () { super ("exists", Boolean.TYPE, "Exists in JAR", "Whether or not the named resource is actually included in the JAR."); } public Object getValue () throws InvocationTargetException { try { Iterator it = provider.getFiles ().iterator (); while (it.hasNext ()) { FileObject fo = (FileObject) it.next (); if (fo.getPackageNameExt ('/', '.').equals (val)) return Boolean.TRUE; } return Boolean.FALSE; } catch (IOException ioe) { throw new InvocationTargetException (ioe); } } } xtra.put (new ExistsProp ()); if (style == CategoryNode.STYLE_SECTION) { class SectionProp extends PropertySupport.ReadWrite { Attributes.Name tag; public SectionProp (Attributes.Name tag, String displayName, String shortDescription) { super (tag.toString (), String.class, displayName, shortDescription); this.tag = tag; } // XXX handle jarcontent == null etc. public Object getValue () throws InvocationTargetException { try { String dispname = provider.getManifest ().getAttributes (val).getValue (tag); return (dispname == null) ? "" : dispname; } catch (IOException ioe) { throw new InvocationTargetException (ioe); } } public void setValue (Object nue) throws IllegalArgumentException, InvocationTargetException { if (! (nue instanceof String)) throw new IllegalArgumentException (); try { Manifest mani = provider.getManifest (); if (nue.equals ("")) mani.getAttributes (val).remove (tag); else mani.getAttributes (val).put (tag, nue); provider.setManifest (mani); } catch (IOException ioe) { throw new InvocationTargetException (ioe); } } public void restoreDefaultValue () throws IllegalArgumentException, InvocationTargetException { setValue (""); } public boolean supportsDefaultValue () { return true; } } if (((String) type).equalsIgnoreCase (ModuleDescription.SECTION_FILESYSTEM)) { xtra.put (new SectionProp (ModuleDescription.TAG_FILESYSTEM_NAME, "Display Name", "Display name for this file system (as will be displayed on Repository Settings popups).")); // XXX proped to browse to *.hs file: xtra.put (new SectionProp (ModuleDescription.TAG_FILESYSTEM_HELP, "Help Set", "Path to a HelpSet.hs file for this file system, in the format com.mycom.HelpSet (like a class name).")); } else if (((String) type).equalsIgnoreCase (ModuleDescription.SECTION_LOADER)) { // XXX propeds to browse to *.class file whose source cookie says that it is a subclass of DataObject xtra.put (new SectionProp (ModuleDescription.TAG_INSTALL_AFTER, "Install After", "DataObject representation class(es) of loader(s) to install this one after (comma-separated class names).")); xtra.put (new SectionProp (ModuleDescription.TAG_INSTALL_BEFORE, "Install Before", "DataObject representation class(es) of loader(s) to install this one before (comma-separated class names).")); } else if (((String) type).equalsIgnoreCase (ModuleDescription.SECTION_SERVICE)) { // XXX proped xtra.put (new SectionProp (ModuleDescription.TAG_SERVICE_DEFAULT, "Is Default", "Whether or not this class of service is the default for its category (True or False).")); } else if (((String) type).equalsIgnoreCase (ModuleDescription.SECTION_NODE)) { // XXX proped xtra.put (new SectionProp (ModuleDescription.TAG_NODE_TYPE, "Node Type", "Where to install this node to.")); } } // STYLE_SECTION } return xtra; } } /* * Log * 17 Gandalf 1.16 1/26/00 Jesse Glick Manifest handling * changed--now more dynamic, synched properly with open document as for * real file types. * 16 Gandalf 1.15 1/22/00 Jesse Glick Manifest files can now * be recognized, not just JARs. * 15 Gandalf 1.14 11/25/99 Jesse Glick * 14 Gandalf 1.13 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 13 Gandalf 1.12 10/6/99 Jesse Glick Added table of contents, * anchored context help. * 12 Gandalf 1.11 10/5/99 Jesse Glick Sundry API changes * affecting me. * 11 Gandalf 1.10 9/30/99 Jesse Glick Package rename and misc. * 10 Gandalf 1.9 9/20/99 Jesse Glick Slick group pasting * (required fix in ExplorerActions). * 9 Gandalf 1.8 9/16/99 Jesse Glick Package change. * 8 Gandalf 1.7 9/16/99 Jesse Glick Changed to work in * recent builds again; filter node deletion fix. * 7 Gandalf 1.6 9/14/99 Jesse Glick Default values. * 6 Gandalf 1.5 9/14/99 Jesse Glick Added existence prop, * commented-out props for service types. Also, deletion warns about * content not being removed. But, deletion no longer updates the view. * And sometimes filter nodes are not created properly after a paste. Very * mysterious. * 5 Gandalf 1.4 9/13/99 Jesse Glick Got deletion to work. * 4 Gandalf 1.3 9/13/99 Jesse Glick Minor fixes. * 3 Gandalf 1.2 9/13/99 Jesse Glick Some bugfixes, all * section props implemented. * 2 Gandalf 1.1 9/13/99 Jesse Glick Starting to add * properties. * 1 Gandalf 1.0 9/13/99 Jesse Glick * $ */